home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / Python 1.3 / source code / Tools / scripts / h2py.py < prev    next >
Encoding:
Python Source  |  1995-12-17  |  3.9 KB  |  142 lines  |  [TEXT/R*ch]

  1. #! /usr/local/bin/python
  2.  
  3. # Read #define's and translate to Python code.
  4. # Handle #include statements.
  5. # Handle #define macros with one argument.
  6. # Anything that isn't recognized or doesn't translate into valid
  7. # Python is ignored.
  8.  
  9. # Without filename arguments, acts as a filter.
  10. # If one or more filenames are given, output is written to corresponding
  11. # filenames in the local directory, translated to all uppercase, with
  12. # the extension replaced by ".py".
  13.  
  14. # By passing one or more options of the form "-i regular_expression"
  15. # you can specify additional strings to be ignored.  This is useful
  16. # e.g. to ignore casts to u_long: simply specify "-i '(u_long)'".
  17.  
  18. # XXX To do:
  19. # - turn trailing C comments into Python comments
  20. # - turn C Boolean operators "&& || !" into Python "and or not"
  21. # - what to do about #if(def)?
  22. # - what to do about macros with multiple parameters?
  23.  
  24. import sys, regex, regsub, string, getopt, os
  25.  
  26. p_define = regex.compile('^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)[\t ]+')
  27.  
  28. p_macro = regex.compile(
  29.   '^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)(\([_a-zA-Z][_a-zA-Z0-9]*\))[\t ]+')
  30.  
  31. p_include = regex.compile('^#[\t ]*include[\t ]+<\([a-zA-Z0-9_/\.]+\)')
  32.  
  33. p_comment = regex.compile('/\*\([^*]+\|\*+[^/]\)*\(\*+/\)?')
  34.  
  35. ignores = [p_comment]
  36.  
  37. p_char = regex.compile("'\(\\\\.[^\\\\]*\|[^\\\\]\)'")
  38.  
  39. filedict = {}
  40.  
  41. try:
  42.     searchdirs=string.splitfields(os.environ['include'],';')
  43. except KeyError:
  44.     try:
  45.         searchdirs=string.splitfields(os.environ['INCLUDE'],';')
  46.     except KeyError:
  47.         searchdirs=['/usr/include']
  48.  
  49. def main():
  50.     opts, args = getopt.getopt(sys.argv[1:], 'i:')
  51.     for o, a in opts:
  52.         if o == '-i':
  53.             ignores.append(regex.compile(a))
  54.     if not args:
  55.         args = ['-']
  56.     for filename in args:
  57.         if filename == '-':
  58.             sys.stdout.write('# Generated by h2py from stdin\n')
  59.             process(sys.stdin, sys.stdout)
  60.         else:
  61.             fp = open(filename, 'r')
  62.             outfile = os.path.basename(filename)
  63.             i = string.rfind(outfile, '.')
  64.             if i > 0: outfile = outfile[:i]
  65.             outfile = string.upper(outfile)
  66.             outfile = outfile + '.py'
  67.             outfp = open(outfile, 'w')
  68.             outfp.write('# Generated by h2py from %s\n' % filename)
  69.             filedict = {}
  70.             for dir in searchdirs:
  71.                 if filename[:len(dir)] == dir:
  72.                     filedict[filename[len(dir)+1:]] = None    # no '/' trailing
  73.                     break
  74.             process(fp, outfp)
  75.             outfp.close()
  76.             fp.close()
  77.  
  78. def process(fp, outfp, env = {}):
  79.     lineno = 0
  80.     while 1:
  81.         line = fp.readline()
  82.         if not line: break
  83.         lineno = lineno + 1
  84.         n = p_define.match(line)
  85.         if n >= 0:
  86.             # gobble up continuation lines
  87.             while line[-2:] == '\\\n':
  88.                 nextline = fp.readline()
  89.                 if not nextline: break
  90.                 lineno = lineno + 1
  91.                 line = line + nextline
  92.             name = p_define.group(1)
  93.             body = line[n:]
  94.             # replace ignored patterns by spaces
  95.             for p in ignores:
  96.                 body = regsub.gsub(p, ' ', body)
  97.             # replace char literals by ord(...)
  98.             body = regsub.gsub(p_char, 'ord(\\0)', body)
  99.             stmt = '%s = %s\n' % (name, string.strip(body))
  100.             ok = 0
  101.             try:
  102.                 exec stmt in env
  103.             except:
  104.                 sys.stderr.write('Skipping: %s' % stmt)
  105.             else:
  106.                 outfp.write(stmt)
  107.         n =p_macro.match(line)
  108.         if n >= 0:
  109.             macro, arg = p_macro.group(1, 2)
  110.             body = line[n:]
  111.             for p in ignores:
  112.                 body = regsub.gsub(p, ' ', body)
  113.             body = regsub.gsub(p_char, 'ord(\\0)', body)
  114.             stmt = 'def %s(%s): return %s\n' % (macro, arg, body)
  115.             try:
  116.                 exec stmt in env
  117.             except:
  118.                 sys.stderr.write('Skipping: %s' % stmt)
  119.             else:
  120.                 outfp.write(stmt)
  121.         if p_include.match(line) >= 0:
  122.             regs = p_include.regs
  123.             a, b = regs[1]
  124.             filename = line[a:b]
  125.             if not filedict.has_key(filename):
  126.                 filedict[filename] = None
  127.                 inclfp = None
  128.                 for dir in searchdirs:
  129.                     try:
  130.                         inclfp = open(dir + '/' + filename, 'r')
  131.                         break
  132.                     except IOError:
  133.                         pass
  134.                 if inclfp:
  135.                     outfp.write(
  136.                         '\n# Included from %s\n' % filename)
  137.                     process(inclfp, outfp, env)
  138.                 else:
  139.                     sys.stderr.write('Warning - could not find file %s' % filename)
  140.  
  141. main()
  142.